<template>
  <Menu
    v-bind="getBindValues"
    :activeName="menuState.activeName"
    :openNames="getOpenKeys"
    :class="prefixCls"
    :activeSubMenuNames="menuState.activeSubMenuNames"
    @select="handleSelect"
  >
    <template v-for="item in items" :key="item.path">
      <SimpleSubMenu
        :item="item"
        :parent="true"
        :collapsedShowTitle="collapsedShowTitle"
        :collapse="collapse"
      />
    </template>
  </Menu>
</template>
<script lang="ts" setup>
  import type { MenuState } from './types'
  import type { Menu as MenuType } from '@/router/types'
  import type { RouteLocationNormalizedLoaded } from 'vue-router'
  import { computed, ref, unref, reactive, toRefs, watch, PropType, useAttrs } from 'vue'
  import { useDesign } from '@/hooks/web/useDesign'
  import Menu from './components/Menu.vue'
  import SimpleSubMenu from './SimpleSubMenu.vue'
  import { listenerRouteChange } from '@/logics/mitt/routeChange'
  import { propTypes } from '@/utils/propTypes'
  import { REDIRECT_NAME } from '@/router/constant'
  import { useRouter } from 'vue-router'
  import { isFunction, getOutsideUrl } from '@/utils/is'
  import { openWindow } from '@/utils'
  import { useOpenKeys } from './useOpenKeys'

  defineOptions({ name: 'SimpleMenu', inheritAttrs: false })

  const props = defineProps({
    items: {
      type: Array as PropType<MenuType[]>,
      default: () => [],
    },
    collapse: propTypes.bool,
    mixSider: propTypes.bool,
    theme: propTypes.string,
    accordion: propTypes.bool.def(true),
    collapsedShowTitle: propTypes.bool,
    beforeClickFn: {
      type: Function as PropType<(key: string) => Promise<boolean>>,
    },
    isSplitMenu: propTypes.bool,
  })

  const emit = defineEmits(['menuClick'])

  const attrs = useAttrs()

  const currentActiveMenu = ref('')
  const isClickGo = ref(false)

  const menuState = reactive<MenuState>({
    activeName: '',
    openNames: [],
    activeSubMenuNames: [],
  })

  const { currentRoute } = useRouter()
  const { prefixCls } = useDesign('simple-menu')
  const { items, accordion, mixSider, collapse } = toRefs(props)

  const { setOpenKeys, getOpenKeys } = useOpenKeys(
    menuState,
    items,
    accordion,
    mixSider as any,
    collapse as any,
  )

  const getBindValues = computed(() => ({ ...attrs, ...props }))

  watch(
    () => props.collapse,
    (collapse) => {
      if (collapse) {
        menuState.openNames = []
      } else {
        setOpenKeys(currentRoute.value.path)
      }
    },
    { immediate: true },
  )

  watch(
    () => props.items,
    () => {
      if (!props.isSplitMenu) {
        return
      }
      setOpenKeys(currentRoute.value.path)
    },
    { flush: 'post' },
  )

  listenerRouteChange((route) => {
    if (route.name === REDIRECT_NAME) return

    currentActiveMenu.value = route.meta?.currentActiveMenu as string
    handleMenuChange(route)

    if (unref(currentActiveMenu)) {
      menuState.activeName = unref(currentActiveMenu)
      setOpenKeys(unref(currentActiveMenu))
    }
  })

  async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
    if (unref(isClickGo)) {
      isClickGo.value = false
      return
    }
    const path = (route || unref(currentRoute)).path

    menuState.activeName = path

    setOpenKeys(path)
  }

  async function handleSelect(key: string) {
    // 判断是否需要通过外部打开
    const path = getOutsideUrl(key)
    if (path) {
      openWindow(path)
      return
    }
    const { beforeClickFn } = props
    if (beforeClickFn && isFunction(beforeClickFn)) {
      const flag = await beforeClickFn(key)
      if (!flag) return
    }

    emit('menuClick', key)

    isClickGo.value = true
    setOpenKeys(key)
    menuState.activeName = key
  }
</script>
<style lang="less">
  @import url('./index.less');
</style>
